package com.heima.gateway.filter;

import com.heima.common.enums.UserEnum;
import com.heima.common.util.AppJwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 全局过滤器：校验访问网关提交token是否合法，将用户信息设置到请求头，将请求路由到其他微服务中
 *
 * @author: itheima
 * @create: 2022-01-14 11:10
 */
@Slf4j
@Component
public class AuthFilter implements GlobalFilter, Ordered {


    /**
     * 过滤器逻辑：获取请求中提交令牌、验证令牌、获取令牌中载荷信息、将用户ID设置到请求头中、路由到其他微服务
     *
     * @param exchange 封装请求，响应对象
     * @param chain    过滤器链
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.通过exchange对象获取请求、响应对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        //2.通过request获取客户端请求地址，判断是否需要进行校验，登录请求直接放行
        String url = request.getURI().getPath();
        if (url.contains("/login")) {
            //登录直接放行
            return chain.filter(exchange);
        }
        //3.访问该请求需要进行拦截，获取客户端在头部提交令牌
        String token = request.getHeaders().getFirst("token");
        if (StringUtils.isBlank(token)) {
            //客户端没有提交令牌-非法请求，直接返回401未授权(登录)
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        //4.校验令牌合法性  获取载荷中用户信息 ，将用户信息封装到请求对象中。路由到目标微服务中
        //4.1 获取载荷信息
        try {
            Claims claims = AppJwtUtil.getClaimsBody(token);
            //4.2 校验令牌合法 -1：有效，0：有效
            int result = AppJwtUtil.verifyToken(claims);
            if (result == -1 || result == 0) {
                //4.3 从载荷中获取用户ID 用户名称
                Object userId = claims.get("userId");
                Object userName = claims.get("userName");
                //4.4 将用户信息封装到请求对象中
                request.mutate().header("userId", userId.toString());
                request.mutate().header("userName", userName.toString());
                //4.3 路由到下一个过滤器 或者目标微服务
                return chain.filter(exchange);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        //其他情况统一返回401
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        return response.setComplete();
    }


    /**
     * 过滤器执行顺序，数值越小优先级越高
     *
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
